#include "linux/of.h"
#include "linux/printk.h"
#include "linux/kthread.h"
#include "linux/slab.h"
#include "linux/wait.h"
#include "linux/err.h"
#include "linux/sched.h"
#include "linux/types.h"
#include "asm/ptrace.h"
#include "linux/errno.h"
#include "linux/irq.h"
#include "linux/kthread.h"
#include "linux/irqdesc.h"
#include "linux/interrupt.h"
#include "settings.h"

#include "internals.h"

void disable_irq(unsigned int irq)
{

}

void __enable_irq(struct irq_desc *desc, unsigned int irq)
{

}

static irqreturn_t irq_default_primary_handler(int irq, void *dev_id)
{
	return IRQ_WAKE_THREAD;
}

static void irq_setup_forced_threading(struct irqaction *new)
{
    if (!force_irqthreads)
        return;
    if (new->flags & (IRQF_NO_THREAD | IRQF_PERCPU | IRQF_ONESHOT))
        return;

    new->flags |= IRQF_ONESHOT;

    if (!new->thread_fn)
    {
        set_bit(IRQTF_FORCED_THREAD, &new->thread_flags);
        new->thread_fn = new->handler;
        new->handler = irq_default_primary_handler;
    }
}

static int irq_request_resources(struct irq_desc *desc)
{
    struct irq_data *d = &desc->irq_data;
    struct irq_chip *c = d->chip;

    return c->irq_request_resources ? c->irq_request_resources(d) : 0;
}

int __irq_set_trigger(struct irq_desc *desc, unsigned int irq, unsigned long flags)
{
    return 0;
}

static int irq_thread(void *data)
{
    return 0;
}

/*
中断线程嵌套：
在 Linux 中断子系统中，“嵌套到其他线程”指的是一个中断的处理线程（threaded handler）本身是在另一个中断线程上下文中被触发的，即该中断是作为另一个中断线程的“子中断”来处理的。
典型场景：有些中断控制器（如 GPIO 控制器）本身挂在主中断控制器（如 GIC）下，GPIO 控制器的中断会被主中断线程唤醒后再分发到各个 GPIO 线的线程，这种情况下 GPIO 线的线程就是“嵌套线程”。
代码中体现：irq_settings_is_nested_thread(desc) 返回 true，表示该中断 action 不是直接由硬件中断触发，而是由另一个线程 handler 间接触发。

oneshot:
RQF_ONESHOT表示在硬中断处理程序（hardirq handler）执行完成后，该中断不会被自动重新启用。
这个标志主要用于线程化中断（threaded interrupts）场景，因为这些中断需要保持irq线处于禁用状态，直到中断处理完全完成。
具体来说，当一个中断被标记为IRQF_ONESHOT时：
1 中断触发后，内核会执行硬中断处理程序（top-half）
2 硬中断处理程序执行完成后，该中断线不会被自动重新启用
3 系统会调度执行对应的中断线程处理程序（bottom-half/threaded handler）
4 只有当中断线程处理程序也执行完毕后，中断线才会被重新启用
这种机制对于某些特殊硬件很重要，特别是那些在中断服务程序执行期间不能被重复触发的设备。
如果不使用IRQF_ONESHOT，当一个中断被线程化处理时，该中断可能会在处理过程中再次触发，导致中断风暴或数据不一致问题

thread_mask的使用及用法：
thread_mask 是用于标识和管理共享中断（shared IRQ）下多个线程化 handler 的唯一性的掩码（bitmask）。
在一个中断线上，可能有多个设备共享（IRQF_SHARED），每个设备都可以有自己的线程 handler。
为了区分和管理这些线程，内核为每个 action 分配一个唯一的 thread_mask（如 1<<0, 1<<1, ...）。
这些 mask 会被 or 到 desc->threads_oneshot（或 desc->threads_active）中，用于跟踪哪些线程 handler 被唤醒、哪些还在运行。

thread_mask分配：在 __setup_irq 里，遍历所有已存在的 action，把它们的 thread_mask 做 or 运算，找到第一个为 0 的位，分配给新 action。new->thread_mask = 1 << ffz(thread_mask);
唤醒线程：当主 handler 需要唤醒线程时，会设置对应的 thread_mask 位到 desc->threads_active。
线程结束：线程 handler 处理完后，会清除自己对应的 thread_mask 位。
中断 unmask：只有当所有共享线程 handler 都处理完（即 desc->threads_active == 0），才会重新使能（unmask）中断线，防止重复进中断

thread_mask 举例:
假设有 3 个设备共享同一个中断线，每个设备的 thread_mask 分别为 1、2、4（即 0b001、0b010、0b100）：
某次中断发生，设备1和设备3都需要唤醒线程，则 desc->threads_active = 0b101。
设备1线程处理完，清除自己的 bit，变成 0b100。
设备3线程也处理完，变成 0b000，此时才会 unmask 中断线。
 */
static int __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
{
    struct irqaction *old, **old_ptr;
    unsigned long thread_mask = 0;
    int ret, nested = 0, shared = 0;

    if (!desc)
        return -EINVAL;

    //nested = irq_settings_is_nested_thread(desc);
    //if (nested)
    //{

    //}
    //else
    {
        if (irq_settings_can_thread(desc))
            irq_setup_forced_threading(new);
    }
    
    if (new->thread_fn && !nested)
    {
        struct task_struct *t;
        t = kthread_create(irq_thread, new, "%s", new->name);
        if (IS_ERR(t))
        {
            ret = PTR_ERR(t);
            printk("Failed to create thread for irq %d: %d\n", irq, ret);
            return ret;
        }

        //staticstruct sched_param param = {
            //.sched_priority = MAX_USER_RT_PRIO / 2,
        //};
        //sched_setscheduler_nocheck(t, SCHED_FIFO, &param);

        //get_tack_struct(t);
        new->thread = t;

        set_bit(IRQTF_AFFINITY, &new->thread_flags);
    }

    //if (desc->irq_data.chip->flags & IRQCHIP_ONESHOT_SAFE)
		//new->flags &= ~IRQF_ONESHOT;
    
    //raw_spin_lock_irqsave(&desc->lock, flags);
    old_ptr = &desc->action;
	old = *old_ptr;
    if (old)
    {
        if (!((old->flags & new->flags) & IRQF_SHARED) ||
            ((old->flags ^ new->flags) & IRQF_TRIGGER_MASK) ||
            ((old->flags ^ new->flags) & IRQF_ONESHOT))
            goto mismatch;

        if ((old->flags & IRQF_PERCPU) != (new->flags & IRQF_PERCPU))
            goto mismatch;

        do
        {
            thread_mask |= old->thread_mask;
            old_ptr = &old->next;
            old = *old_ptr;
        } while (old);
        shared = 1;
    }

    if (new->flags & IRQF_ONESHOT)
    {
        if (thread_mask == ~0UL)
        {
            ret = -EBUSY;
            goto out_mask;
        }
        new->thread_mask = 1 << ffz(thread_mask);
    }
    else if (new->handler == irq_default_primary_handler && !(desc->irq_data.chip->flags & IRQCHIP_ONESHOT_SAFE))
    {
        printk("Threaded irq requested with handler=NULL and !ONESHOT for irq %d\n", irq);
        ret = -EINVAL;
        goto out_mask;
    }

    /*
     * irq_request_resources的作用是为中断分配底层硬件资源（如中断控制器的通道、寄存器等）。
     * 只有在第一个handler注册到该irq时（即!shared，当前没有其他handler），才需要分配这些资源。
     * 后续如果是共享中断（shared），只是把新的handler链入action链表，不需要重复分配硬件资源。
     */
    if (!shared)
    {
        ret = irq_request_resources(desc);
        if (ret)
        {
            printk("Failed to request resources for %s (irq %d) on irqchip %s\n", new->name, irq, desc->irq_data.chip->name);
            goto out_mask;
        }

        init_waitqueue_head(&desc->wait_for_threads);
        if (new->flags & IRQF_TRIGGER_MASK)
        {
            ret = __irq_set_trigger(desc, irq, new->flags & IRQF_TRIGGER_MASK);
            if (ret)
                goto out_mask;
        }
#if 0
        desc->istate &= ~(IRQS_AUTODETECT | IRQS_SPURIOUS_DISABLED | IRQS_ONESHOT | IRQS_WAITING);
        irqd_clear(&desc->irq_data, IRQD_IRQ_INPROGRESS);

        if (new->flags & IRQF_PERCPU)
        {
            irqd_set(&desc->irq_data, IRQD_PER_CPU);
            irq_settings_set_per_cpu(desc);
        }

        if (new->flags & IRQF_ONESHOT)
            desc->istate |= IRQS_ONESHOT;
#endif

        if (irq_settings_can_autoenable(desc))
            irq_startup(desc, 1);
        else
            /* Undo nested disables: */
            desc->depth = 1;
#if 0
        if (new->flags & IRQF_NOBALANCING)
        {
            irq_settings_set_no_balancing(desc);
            irqd_set(&desc->irq_data, IRQD_NO_BALANCING);
        }
#endif
        //setup_affinity(irq, desc, mask);
    }
    else if (new->flags & IRQF_TRIGGER_MASK)
    {
        unsigned int nmsk = new->flags & IRQF_TRIGGER_MASK;
        unsigned int omsk = irq_settings_get_trigger_mask(desc);

        if (nmsk != omsk)
            printk("irq %d uses trigger mode %u; requested %u\n", irq, nmsk, omsk);
    }

    new->irq = irq;
    *old_ptr = new;

	//irq_pm_install_action(desc, new);

    desc->irq_count = 0;
	desc->irqs_unhandled = 0;

    /*
     * IRQS_SPURIOUS_DISABLED用于标记某个中断因为“虚假中断”（spurious interrupt）被禁用了。
     * 当内核检测到某个中断线频繁产生无效中断（比如没有设备响应），会将其禁用，并设置该标志。
     * 这样做是为了防止系统被无效中断“淹没”，影响性能和稳定性。
     * 当有新的handler注册到该irq时，如果发现IRQS_SPURIOUS_DISABLED被设置，会清除该标志并重新使能中断，给它“第二次机会”。
    */
    if (shared && (desc->istate & IRQS_SPURIOUS_DISABLED))
    {
        desc->istate &= ~IRQS_SPURIOUS_DISABLED;
        __enable_irq(desc, irq);
    }

    if (new->thread)
		wake_up_process(new->thread);

    //raw_spin_unlock_irqrestore(&desc->lock, flags);
    return 0;
    
mismatch:
    ret = -EBUSY;
out_mask:
    //raw_spin_unlock_irqrestore(&desc->lock, flags);
//out_thread:
    if (new->thread)
    {
        struct task_struct *t = new->thread;
        new->thread = NULL;
        kthread_stop(t);
        //put_task_struct(t);
    }

    return ret;
}

int request_threaded_irq(unsigned int irq, irq_handler_t handler, irq_handler_t thread_fn, unsigned long irqflags, char *devname, void *devid)
{
    struct irq_desc *desc;
    struct irqaction *action;
    int retval;

    desc = irq_to_desc(irq);
    if (!desc)
        return -EINVAL;
    
    if (!handler && !thread_fn)
        return -EINVAL;
    
    action = (struct irqaction *)kzalloc(sizeof(struct irqaction), GFP_KERNEL);
    if (!action)
        return -ENOMEM;
    
    action->handler = handler;
    action->thread_fn = thread_fn;
    action->dev_id = devid;
    action->flags = irqflags;
    action->name = devname;
    action->irq = irq;

    //chip_bus_lock(desc);
	retval = __setup_irq(irq, desc, action);
	//chip_bus_sync_unlock(desc);
    if (retval)
        kfree(action);

    return retval;
}

int setup_irq(unsigned int irq, struct irqaction *act)
{
    int retval;
    struct irq_desc *desc = irq_to_desc(irq);

    if (!desc)
        return -EINVAL;

    //chip_bus_lock(desc);
    retval = __setup_irq(irq, desc, act);
    //chip_bus_sync_unlock(desc);

    return retval;
}